﻿/*
    File name:          OppStdViewModel
    File type:          Class
    Author:             Mads Skipper Pedersen 07299
    Creation date:      15-03-2011
    Last modified:      18-05-2011
    Last modified by:   Mads Skipper Pedersen 07299
    Description:        The ViewModel for the standard opperator tab.
                        Here sorted bricks are shown and the last
                        executed script can be start / stopped.
*/

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using i4pro_gruppe_d.Database;
using i4pro_gruppe_d.Types;

namespace OppStd.ViewModel
{
    public class OppStdViewModel : ViewModelBase
    {
        #region Members
        private BackgroundWorker bgw;
        private BackgroundWorker runningScriptBgw;
        private AbstractDatabase db;
        private Antlr.Runtime.Tree.CommonTree scriptCommonTree;
        private Messenger messenger;
        private ProcessManagement.ProcessManagement pm;
        private Thread newThread;
        #endregion
        #region Propertys
        public ObservableCollection<Brick> AllSavedBricks { get; set; }
        public ObservableCollection<Brick> ShownSavedBricks { get; set; }

        private DateTime selectedDate;
        public DateTime SelectedDate
        {
            get
            {
                return selectedDate;
            }
            set
            {
                selectedDate = value;
                RaisePropertyChanged("SelectedDate");
            }
        }

        private DateTime startDate;
        public DateTime StartDate
        {
            get { return startDate; }
            set
            {
                startDate = value;
                RaisePropertyChanged("StartDate");
            }
        }

        private DateTime endDate;
        public DateTime EndDate
        {
            get { return endDate; }
            set
            {
                endDate = value;
                RaisePropertyChanged("EndDate");
            }
        }

        private string startStopButtonText;
        public string StartStopButtonText
        {
            get
            {
                return startStopButtonText;
            }
            set
            {
                startStopButtonText = value;
                RaisePropertyChanged("StartStopButtonText");
            }
        }

        private int height;
        public int Height
        {
            get { return height; }
            set
            {
                height = value;
                RaisePropertyChanged("Height");
            }
        }
        private int length;
        public int Length
        {
            get { return length; }
            set
            {
                length = value;
                RaisePropertyChanged("Length");
            }
        }
        private int width;
        public int Width
        {
            get { return width; }
            set
            {
                width = value;
                RaisePropertyChanged("Width");
            }
        }
        private int weight;
        public int Weight
        {
            get { return weight; }
            set
            {
                weight = value;
                RaisePropertyChanged("Weight");
            }
        }
        #endregion
        #region Constructor
        public OppStdViewModel()
        {
            StartDate = new DateTime(2011, 1, 1);
            EndDate = new DateTime(2011, 7, 31);
            SelectedDate = DateTime.Now;
            StartStopButtonText = "Start";

            AllSavedBricks = new ObservableCollection<Brick>();
            ShownSavedBricks = new ObservableCollection<Brick>();

            AbstractDatabase _db = AbstractDatabase.Instance;
            db = _db;

            messenger = Messenger.Default;
            messenger.Register<Antlr.Runtime.Tree.CommonTree>(this, ScriptRecieved);
            messenger.Register<Brick>(this, BrickAdded);
            messenger.Register<int>(this, "Height", LiveHeightDataRecieved);
            messenger.Register<int>(this, "Length", LiveLengthDataRecieved);
            messenger.Register<int>(this, "Width", LiveWidthDataRecieved);
            messenger.Register<int>(this, "Weight", LiveWeightDataRecieved);
            messenger.Register<bool>(this, "Newbricknotice", ResetLiveData);

            DateChangedExecute();
        }
        #endregion
        #region Commands
        #region Previous History Command
        public ICommand PrevHistory_cmd
        {
            get { return new RelayCommand(PrevHistoryExecute, PrevHistoryCanExecute); }
        }

        private void PrevHistoryExecute()
        {
            SelectedDate = SelectedDate - new TimeSpan(1, 0, 0, 0);
        }

        private bool PrevHistoryCanExecute()
        {
            if (StartDate < SelectedDate)
                return true;
            return false;
        }
        #endregion
        #region Next History Command
        public ICommand NextHistory_cmd
        {
            get { return new RelayCommand(NextHistoryExecute, NextHistoryCanExecute); }
        }

        private void NextHistoryExecute()
        {
            SelectedDate = SelectedDate + new TimeSpan(1, 0, 0, 0);
        }

        private bool NextHistoryCanExecute()
        {
            if (EndDate > SelectedDate)
                return true;
            return false;
        }
        #endregion
        #region Date Selection Changed Command
        public ICommand DateSelectionChanged_Command
        {
            get { return new RelayCommand(DateChangedExecute); }
        }

        private void DateChangedExecute()
        {
            if (SelectedDate < StartDate)
            {
                SelectedDate = StartDate;
                
            }
            else if (SelectedDate > EndDate)
            {
                SelectedDate = EndDate;
            }

            Run_LoadBrickDataFromDB_BGW();
        }
        #endregion
        #region Start stop script Command
        public ICommand StartStop_Cmd
        {
            get { return new RelayCommand(StartStopScriptExecute, StartStopScriptCanExecute); }
        }

        private void StartStopScriptExecute()
        {
            if (StartStopButtonText == "Start")
            {
                newThread = new Thread(new ThreadStart(RunScript));
                newThread.Start();
                StartStopButtonText = "Stop";
                db.NewBatch(DateTime.Now, DateTime.Now);
            }
            else
            {
                //Stop script
                newThread.Abort();
                StartStopButtonText = "Start";
                db.SetBatchEndTime(DateTime.Now);
                messenger.Send("Stopped", "ExecutingCommand");
            }
        }

        private bool StartStopScriptCanExecute()
        {
            return scriptCommonTree != null;
        }
        #endregion
        #region Refresh Brick List Command
        public ICommand RefreshBricksList_Cmd
        {
            get { return new RelayCommand(RefreshBricksList); }
        }

        public void RefreshBricksList()
        {
            DateChangedExecute();
        }
        #endregion
        #endregion
        #region Methods
        private void LiveLengthDataRecieved(int length)
        {
            Length = length;
        }
        private void LiveWidthDataRecieved(int width)
        {
            Width = width;
        }
        private void LiveHeightDataRecieved(int height)
        {
            Height = height;
        }
        private void LiveWeightDataRecieved(int weight)
        {
            Weight = weight;
        }
        private void ResetLiveData(bool b)
        {
            Length = 0;
            Width = 0;
            Height = 0;
            Weight = 0;
        }
        private void ScriptRecieved(Antlr.Runtime.Tree.CommonTree script)
        {
            scriptCommonTree = script;
        }

        private void BrickAdded(Brick brick)
        {
            if(SelectedDate.Date == DateTime.Now.Date)
                ShownSavedBricks.Add(brick);
        }

        private void RunScript()
        {
            try
            {
                pm = new ProcessManagement.ProcessManagement(true);
                pm.DFSRecursiveRunThroughOfAST(scriptCommonTree);
                messenger.Send("Finished running script", "ExecutingCommand");
                StartStopButtonText = "Start";
            }
            catch (ThreadAbortException abortException)
            {
                Console.WriteLine((string)abortException.ExceptionState);
            }
        }

        private void Run_LoadBrickDataFromDB_BGW()
        {
            bgw = new BackgroundWorker();
            bgw.DoWork += Bgw_LoadBrickDataFromDB_DoWork;
            bgw.RunWorkerCompleted += Bgw_LoadBrickDataFromDB_Complete;
            bgw.RunWorkerAsync();
        }
        #endregion
        #region Background worker
        private void Bgw_LoadBrickDataFromDB_DoWork(object sender, DoWorkEventArgs e)
        {
            List<Brick> tempList = new List<Brick>();
            tempList = db.ReadBrick(selectedDate);
            AllSavedBricks.Clear();

            foreach (var brick in tempList)
            {
                AllSavedBricks.Add(brick);
            }
        }

        private void Bgw_LoadBrickDataFromDB_Complete(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                ShownSavedBricks.Clear();
                foreach (var brick in AllSavedBricks)
                {
                    ShownSavedBricks.Add(brick);
                }
            }
            
            catch(Exception)
            {
                
            }
        }
        #endregion
    }
}
